from tqdm import tqdm
import datetime, copy, re, random
from structure import *
from typing import List, Dict, Any, Tuple
from rule import *
from typing import List, Dict, Any, Callable


def mock_structure(strut: Strut, init_time: str = None) -> Dict[str, Any]:
    for field in strut.fields:
        if init_time and field.type == "date":
            # 正则表达式模式
            field.rule = f"date@{init_time}"

        field.value = rule(field.rule, ruleAnalysis)


# 扩展属性获取
def supplement_args(
    extra_elements: ExtraElements, args_dict: Dict[str, Any]
) -> Dict[str, Any]:
    dbType = (
        extra_elements.dbType
        if extra_elements.dbType in ("mysql", "oracle")
        else args_dict.get("dbType")
    )
    format = (
        extra_elements.format
        if extra_elements.format in ("csv", "xlsx", "sql", "json")
        else args_dict.get("format")
    )

    args_dict["dbType"] = dbType
    args_dict["format"] = format

    return {**args_dict}


def config_verification(data_structure: DataStructure, file_name: str) -> bool:
    # 主结构名必须定义
    if len(data_structure.main) == 0:
        print(f"{file_name}配置文件中主结构未定义，返回为空")
        return False

    # 主结构相关集合必须定义
    main_structures = set(data_structure.main)
    defined_struts = {strut.name for strut in data_structure.struts}
    if main_structures - defined_struts:
        print(f"{file_name}配置文件中主结构名无法映照相关结构体，请检查配置中结构定义")
        return False

    return True


def calculate_value(quote_value: str, rule_value: str, type: str):
    try:
        if rule is None or rule == "":
            return quote_value

        cal_value = ""

        if type == "num":
            # 检查quote_value的符号
            if quote_value.startswith("-"):
                cal_value = str(
                    float(quote_value) + float(rule(rule_value, ruleAnalysis))
                )  # 相减
            else:
                cal_value = str(
                    float(quote_value) + float(rule(rule_value, ruleAnalysis))
                )  # 相加

            # 转换为整数如果没有小数部分
            if "." not in cal_value:
                cal_value = str(int(float(cal_value)))  # 确保转换为整数时正确处理

            # 去掉多余的零和小数点
            cal_value = cal_value.rstrip("0").rstrip(".")
        elif type == "date":
            date_formats = [
                "%Y-%m-%d",  # 年-月-日
                "%Y/%m/%d",  # 年/月/日
                "%d-%m-%Y",  # 日-月-年
                "%d/%m/%Y",  # 日/月/年
                "%Y-%m-%d %H:%M:%S",  # 年-月-日 时:分:秒
                "%Y/%m/%d %H:%M:%S",  # 年/月/日 时:分:秒
                "%d-%m-%Y %H:%M:%S",  # 日-月-年 时:分:秒
                "%d/%m/%Y %H:%M:%S",  # 日/月/年 时:分:秒
                "%Y-%m-%d %H:%M",  # 年-月-日 时:分
                "%Y/%m/%d %H:%M",  # 年/月/日 时:分
                "%d-%m-%Y %H:%M",  # 日-月-年 时:分
                "%d/%m/%Y %H:%M",  # 日/月/年 时:分
                "%Y-%m-%d %H:%M:%S.%f",  # 年-月-日 时:分:秒.微秒
                "%Y/%m/%d %H:%M:%S.%f",  # 年/月/日 时:分:秒.微秒
                "%d-%m-%Y %H:%M:%S.%f",  # 日-月-年 时:分:秒.微秒
                "%d/%m/%Y %H:%M:%S.%f",  # 日/月/年 时:分:秒.微秒
            ]

            for fmt in date_formats:
                try:
                    # 尝试解析日期时间字符串
                    parsed_datetime = datetime.datetime.strptime(quote_value, fmt)
                    # 加上指定的秒数
                    adjusted_datetime = parsed_datetime + datetime.timedelta(
                        seconds=int(rule_value)
                    )
                    # 返回格式化后的日期时间字符串
                    cal_value = adjusted_datetime.strftime("%Y-%m-%d %H:%M:%S")
                    break
                except ValueError:

                    continue  # 如果解析失败，则尝试下一个格式)

            if not cal_value:
                cal_value = quote_value
        else:
            cal_value = quote_value

        return cal_value
    except:
        return quote_value


def calculate_rule(cal_field: StrutField, quote_value: str, rule: str):
    pass
    # cal_field.value = calculate_value(quote_value, rule, cal_field.type)
    # try:
    #     if rule is None or rule == "":
    #         cal_field.value = quote_value
    #         return

    #     if cal_field.type == "num":
    #         # 检查quote_value的符号
    #         if quote_value.startswith("-"):
    #             cal_field.value = str(float(quote_value) + float(rule))  # 相减
    #         else:
    #             cal_field.value = str(float(quote_value) + float(rule))  # 相加

    #         # 转换为整数如果没有小数部分
    #         if "." not in cal_field.value:
    #             cal_field.value = str(
    #                 int(float(cal_field.value))
    #             )  # 确保转换为整数时正确处理

    #         # 去掉多余的零和小数点
    #         cal_field.value = cal_field.value.rstrip("0").rstrip(".")
    #     elif cal_field.type == "date":
    #         # 先转换时间为秒
    #         cal_field.value = (
    #             datetime.datetime.strptime(
    #                 quote_value,
    #                 "%Y-%m-%d %H:%M:%S",
    #             )
    #             + datetime.timedelta(seconds=int(rule))
    #         ).strftime("%Y-%m-%d %H:%M:%S")
    #     else:
    #         cal_field.value = quote_value + rule
    # except:
    #     pass


def association_mapping_data(
    field_reflect: FieldReflect, association_strut: Strut, main_struct_data: Strut
):
    for field_rel in field_reflect:
        # 获取主结构字段值
        main_field_value = next(
            (
                main_field.value
                for main_field in main_struct_data.fields
                if main_field.field == field_rel.main_field
            ),
            None,
        )

        # 获取关联结构字段
        association_field = next(
            (
                association_field
                for association_field in association_strut.fields
                if association_field.field == field_rel.association_field
            ),
            None,
        )

        if not association_field:
            continue

        # calculate_rule(association_field, main_field_value, field_rel.rule)
        association_field.value = calculate_value(
            main_field_value,
            field_rel.rule,
            association_field.type,
        )


def cal_rule_func(field_rel, strut_field, index_j, index_i):
    cal_rule = None
    if index_i is not None:
        try:
            cal_rule = (
                str(
                    abs(int(rule(field_rel.rule, ruleAnalysis)))
                    * (index_j + 1)
                    * (index_i + 1)
                )  # 使用绝对值进行乘法
                if (strut_field.type == "num" or strut_field.type == "date")
                and field_rel.rule is not None
                else rule(field_rel.rule, ruleAnalysis)
            )

            # 如果 field_rel.rule 是负数，则将符号应用到 cal_rule
            if (
                (strut_field.type == "num" or strut_field.type == "date")
                and field_rel.rule is not None
                and int(field_rel.rule) < 0
            ):
                cal_rule = "-" + cal_rule
        except:
            cal_rule = (
                "0"
                if (strut_field.type == "num" or strut_field.type == "date")
                and field_rel.rule is not None
                else field_rel.rule
            )
    else:
        try:
            cal_rule = (
                str(
                    abs(int(rule(field_rel.rule, ruleAnalysis))) * (index_j + 1)
                )  # 使用绝对值进行乘法
                if (strut_field.type == "num" or strut_field.type == "date")
                and field_rel.rule is not None
                else rule(field_rel.rule, ruleAnalysis)
            )

            # 如果 field_rel.rule 是负数，则将符号应用到 cal_rule
            if (
                (strut_field.type == "num" or strut_field.type == "date")
                and field_rel.rule is not None
                and int(field_rel.rule) < 0
            ):
                cal_rule = "-" + cal_rule
        except:
            cal_rule = (
                "0"
                if (strut_field.type == "num" or strut_field.type == "date")
                and field_rel.rule is not None
                else field_rel.rule
            )

    return cal_rule


def get_data_type(value: str):
    """
    根据输入的字符串，推测其数据类型：日期、数字或字符串。

    :param value: 输入字符串
    :return: 数据类型（"date", "num", "str"）
    """
    # 尝试解析日期
    date_formats = [
        "%Y-%m-%d",  # 年-月-日
        "%Y/%m/%d",  # 年/月/日
        "%d-%m-%Y",  # 日-月-年
        "%d/%m/%Y",  # 日/月/年
        "%Y-%m-%d %H:%M:%S",  # 年-月-日 时:分:秒
        "%Y/%m/%d %H:%M:%S",  # 年/月/日 时:分:秒
        "%d-%m-%Y %H:%M:%S",  # 日-月-年 时:分:秒
        "%d/%m/%Y %H:%M:%S",  # 日/月/年 时:分:秒
        "%Y-%m-%d %H:%M",  # 年-月-日 时:分
        "%Y/%m/%d %H:%M",  # 年/月/日 时:分
        "%d-%m-%Y %H:%M",  # 日-月-年 时:分
        "%d/%m/%Y %H:%M",  # 日/月/年 时:分
        "%Y-%m-%d %H:%M:%S.%f",  # 年-月-日 时:分:秒.微秒
        "%Y/%m/%d %H:%M:%S.%f",  # 年/月/日 时:分:秒.微秒
        "%d-%m-%Y %H:%M:%S.%f",  # 日-月-年 时:分:秒.微秒
        "%d/%m/%Y %H:%M:%S.%f",  # 日/月/年 时:分:秒.微秒
    ]

    for fmt in date_formats:
        try:
            datetime.datetime.strptime(value, fmt)
            return "date"
        except ValueError:
            continue

    # 检查是否为数字（整数或浮点数）
    if re.match(r"^-?\d+(\.\d+)?$", value):
        return "num"

    # 默认返回字符串类型
    return "str"


def diff_extra_datas(
    extra_datas_config: ExtraData, diff_group: int = 1
) -> List[List[Any]]:
    """
    挂载数据分组：根据datas_rule判定是否分组，当规则为average根据diff_group确定分组数

    参数：
    - extra_datas_config：挂载数据模块配置
    - diff_group: 分组数量

    引用规则参数分析：
    - datas_rule：数据集规则
     - average(均分) ：与diff_group组合，分组得到数据
     - random(随机)：diff_group 默认为1
     - sequence(顺序) diff_group 默认为1

    - field_rule: 字段规则，提供对挂载数据进行二次计算，支持正则，目前仅可字符串拼接、数值增减、日期秒数增减
    """
    # 挂载的数据集
    quote_datas = extra_datas_config.datas
    # 本地数据集+挂载数据集不存在，返回空集合
    if not quote_datas:
        return []

    # 数据集使用规则
    quote_rule_config = extra_datas_config.quote_rule
    # 数据集规则 average random sequence
    datas_rule = quote_rule_config.datas_rule
    # 数据集中字段规则
    field_rule = quote_rule_config.field_rule

    # 针对于列表中的数据，先进行二次计算
    if field_rule:
        # 按照字段规则，加工初始数据
        for data in quote_datas:
            for key, value in data.items():
                item_field_rule = next(
                    (item.rule for item in field_rule if item.field == key),
                    None,
                )
                if not item_field_rule or (
                    datas_rule == "average" and item_field_rule == "merge"
                ):
                    continue
                # 计算
                data[key] = calculate_value(
                    value, item_field_rule, get_data_type(value)
                )

    if datas_rule == "random":
        quote_datas = random.sample(quote_datas, len(quote_datas))

    if datas_rule != "average":
        diff_group = 1

    # 初始化分组列表
    groups = [[] for _ in range(diff_group)]

    # 计算每个组的大小
    for index, data in enumerate(quote_datas):
        groups[index % diff_group].append(data)

    # 过滤空组
    groups = [group for group in groups if group]

    result = []

    if datas_rule == "average" and field_rule:
        # 提前计算所有需要合并的字段
        merge_keys = [item.field for item in field_rule if item.rule == "merge"]

        # 处理每个组
        for group in groups:
            # 收集每个 quote_data 中的合并值
            merged_values = {
                key: [] for key in merge_keys
            }  # 移到这里，避免每个quote_data初始化

            for quote_data in group:
                for key in merge_keys:
                    if key in quote_data:  # 确保 key 存在于 quote_data 中
                        merged_values[key].append(quote_data[key])

            # 计算合并后的值并更新到 quote_datas
            for key in merge_keys:
                if merged_values[key]:  # 确保列表非空
                    merged_value = ",".join(merged_values[key])
                    for data in group:  # 更新当前组的所有数据
                        data[key] = merged_value

            # 检查是否所有字段都需要合并
            all_merge = all(item.rule == "merge" for item in field_rule)

            # 将结果添加到 result
            if all_merge:
                result.append([group[0]])  # 只保留第一个元素
            else:
                result.append(group)

    else:
        result = groups  # 如果不需要合并，直接返回原始组

    return result


def template_mock_data(
    template_strut: Template,
    strut_instance: Strut,
    main_strut: Strut,
    cal_rule_func: Callable[[FieldReflect, StrutField, int, int], str],
    index_i: int,
    init_time: str,
    mock_data_list: List[Any],
    temp_progress_bar: tqdm,
    extra_datas: List[Dict[str, Any]] | Dict[str, Any],
    field_reflect: FieldReflect,
):

    # 判断extra_datas List 还是 Dict
    extra_datas_list = [None]
    if extra_datas:
        if isinstance(extra_datas, list):
            extra_datas_list = extra_datas
        else:
            extra_datas_list = [extra_datas]

    # 获取挂载数据
    for extra_data in extra_datas_list or [None]:
        for j in range(len(template_strut.datas)):
            temp_progress_bar.total += 1
            temp_progress_bar.update(1)
            strut_instance_copy = copy.deepcopy(strut_instance)
            # 为主结构字段赋值
            if index_i is not None and init_time:
                mock_structure(strut_instance_copy, init_time)
            elif field_reflect and main_strut:
                # 构建模拟数据
                strut_instance_copy = copy.deepcopy(strut_instance)
                mock_structure(strut_instance_copy, None)
                association_mapping_data(field_reflect, strut_instance_copy, main_strut)

            # 继承模板迭代生成数据
            for field_rel in template_strut.relations:
                template_field_value = None
                if field_rel.rule == "quote":
                    # 上述主结构字段也找不到，那就找挂载数据 从 extra_data 获取对应的值
                    if extra_data:
                        template_field_value = extra_data.get(
                            field_rel.data_field, None
                        )
                else:
                    # 从模板datas中获取数据
                    template_field_value = template_strut.datas[j].get(
                        field_rel.data_field, None
                    )

                    # 模板数据找不到 找关联结构字段
                    if not template_field_value:
                        template_field_value = next(
                            (
                                association_field.value
                                for association_field in strut_instance_copy.fields
                                if association_field.field == field_rel.data_field
                            ),
                            None,
                        )

                    # 关联字段找不到 找主结构字段
                    if main_strut and not template_field_value:
                        template_field_value = next(
                            (
                                main_field.value
                                for main_field in main_strut.fields
                                if main_field.field == field_rel.data_field
                            ),
                            None,
                        )

                if template_field_value is None:
                    continue

                # 获取关联结构字段
                association_field = next(
                    (
                        association_field
                        for association_field in strut_instance_copy.fields
                        if association_field.field == field_rel.field
                    ),
                    None,
                )
                if association_field is None:
                    continue
                if field_rel.rule == "quote":
                    association_field.value = template_field_value
                else:
                    cal_rule = cal_rule_func(field_rel, association_field, j, index_i)

                    # calculate_rule(association_field, template_field_value, cal_rule)
                    association_field.value = calculate_value(
                        template_field_value,
                        cal_rule,
                        association_field.type,
                    )

            if mock_data_list is not None:
                mock_data_list.append(strut_instance_copy)


def mock_cycle_data(
    data_structure: DataStructure,
    args: Dict[str, Any],
    cycle_mock_dict: Dict[str, List[Any]],
    mock_list: List[Any],
    num: str,
    cycle_structures: List[str],
    file_name: str,
    time_list: List[str],
):
    progress_bar = tqdm(total=0, desc="主结构/独立子结构数据模拟进度", unit="条")
    # 获取模板信息
    template = data_structure.template

    for cycle_strut_name in cycle_structures:
        # 存储主结构生成的数据
        mock_data_list = []
        # 获取模板结构
        template_strut = next(
            (
                template_strut
                for template_strut in template
                if template_strut.name == cycle_strut_name
            ),
            None,  # 或者其他默认值
        )

        extra_data_group = None
        extra_data_group_len = 0
        if template_strut:
            # 计算所需要获取的分组数，这边不需要去管引用数据集分组规则
            extra_datas_config = template_strut.extra_datas
            # 数据集规则
            datas_rule = extra_datas_config.quote_rule.datas_rule
            diff_group = (len(time_list) or 1) * (num or 1)
            extra_data_group = diff_extra_datas(extra_datas_config, diff_group)
            if datas_rule in ("random", "sequence") and extra_data_group:
                extra_data_group = extra_data_group[0] or []

            extra_data_group_len = len(extra_data_group)

        if not time_list:
            time_list = [None]
        for t, init_time in enumerate(time_list):
            # 过滤data_structure.struts name 与 cycle_strut_name 相等的Struts
            cycle_strut_data = next(
                (
                    strut
                    for strut in data_structure.struts
                    if strut.name == cycle_strut_name
                ),
                None,  # 或者其他默认值
            )

            if cycle_strut_data is None:
                # print(f"没有找到{main_strut_name}结构信息")
                continue

            for i in range(int(num)):
                # print(f"开始生成{cycle_strut_name}结构第{i+1}条数据")
                if template_strut is None:
                    progress_bar.total += 1
                    progress_bar.update(1)
                    # 构建模拟数据
                    cycle_data_instance = copy.deepcopy(cycle_strut_data)
                    mock_structure(cycle_data_instance, init_time)
                    mock_data_list.append(cycle_data_instance)
                else:
                    extra_datas = None
                    # 计算索引，使用取模来处理不够的情况
                    if extra_data_group:
                        index = (t * int(num) + i) % extra_data_group_len
                        extra_datas = extra_data_group[index]

                    template_mock_data(
                        template_strut,
                        cycle_strut_data,
                        None,
                        cal_rule_func,
                        i,
                        init_time,
                        mock_data_list,
                        progress_bar,
                        extra_datas,
                        None,
                    )

        if mock_data_list:
            mock_list.append((file_name, cycle_strut_name, mock_data_list, args))

        for cycle_data_instance in mock_data_list:
            if cycle_data_instance.name in cycle_mock_dict:
                cycle_mock_dict[cycle_data_instance.name].append(cycle_data_instance)
            else:
                cycle_mock_dict[cycle_data_instance.name] = [cycle_data_instance]

    progress_bar.close()


def mock_data(
    config_template: Tuple[str, Dict[str, Any]], args_dict: Dict[str, Any]
) -> List[tuple[str, List[Dict[str, Any]]]]:
    # 模板文件名
    file_name = config_template[0]
    # 模板数据
    file_template = config_template[1]
    # dict 转换 对象
    data_structure = create_data_structure(file_template)

    # 参数校验
    if config_verification(data_structure, file_name) != True:
        return []

    # 扩展元素 补充配置参数
    args = supplement_args(data_structure.extra_elements, args_dict)
    # 获取生成数据指定的时间
    time_list = data_structure.extra_elements.time
    # 获取生成数据的记录数
    num = data_structure.extra_elements.num
    # 获取所有的主结构
    main_structures = list(dict.fromkeys(data_structure.main))
    # 获取所有的关联结构
    association_structures = list(dict.fromkeys(data_structure.association))
    # 模拟生成主结构模板及数据(包含无相关联的子结构)
    main_mock_dict = {}
    # 模拟数据集
    mock_list = []
    # 模板信息
    template = data_structure.template

    print(f"开始模拟生成{file_name}相关结构数据")
    # 获取所有主结构相关的模板
    mock_cycle_data(
        data_structure,
        args,
        main_mock_dict,
        mock_list,
        num,
        main_structures,
        file_name,
        time_list,  # 如果 time_list 为空，则 init_time 为 None
    )

    # 生成关联结构数据
    # 没有任何关联的子结构名称 (在子关系中不存在就要提前单独生成模拟数据)
    no_relation_association = [
        association
        for association in association_structures
        if association
        not in set(relation.association for relation in data_structure.relation)
    ]

    # 单独生没有任何关联的子结构数据
    if no_relation_association:
        mock_cycle_data(
            data_structure,
            args,
            main_mock_dict,
            mock_list,
            num,
            no_relation_association,
            file_name,
            time_list,
        )

    progress_bar = tqdm(total=0, desc="关联子结构数据模拟进度", unit="条")
    # 获取有主子关系的子结构
    has_relation_association = [
        item for item in association_structures if item not in no_relation_association
    ]

    # 开始构建子结构相关的数据
    for association_name in has_relation_association:
        # 找到子结构信息
        association_strut = next(
            (
                strut
                for strut in data_structure.struts
                if strut.name == association_name
            ),
            None,
        )

        # 子结构不存在，跳过
        if not association_strut:
            continue

        # 找到与子结构名称挂钩的子关系
        relations = [
            rel
            for rel in data_structure.relation
            if rel.association == association_name
        ]

        # 结构名称：结构数据 按照结构数据的总量倒序
        main_strut_data = {
            rel.main: main_mock_dict[rel.main]
            for rel in relations
            if rel.main in main_mock_dict
        }

        # 根据结构数据的总量倒序排序
        sorted_main_strut_data = sorted(
            main_strut_data.items(), key=lambda item: len(item[1]), reverse=True
        )

        if not main_strut_data:
            continue

        # 找到模板关系
        template_strut = next(
            (
                template_strut
                for template_strut in template
                if template_strut.name == association_name
            ),
            None,  # 或者其他默认值
        )

        # 依据第一个主结构数据生成
        # 这种可能会找到很多的关系数据
        association_data_list = []
        for index, (struct_name, struct_datas) in enumerate(sorted_main_strut_data):
            # index == 0 按照数据生成对应数量的子结构
            # index > 0 均衡分配生成的子结构条数再映射相关结构数据

            # 关联到的主结构数据未生成或者不存在，跳过
            # 导致原因：数据未生成而被引用，定义的子结构引用了其他子结构名称，并且引用的子结构在当前定义之后
            if not struct_datas:
                continue

            # 查询映射关系
            # 根据 主结构名称 和 关联结构名称 提取关联关系
            field_reflect = next(
                (
                    rel.field_reflect
                    for rel in relations
                    if rel.main == struct_name and rel.association == association_name
                ),
                None,
            )
            extra_data_group = None
            extra_data_group_len = 0
            if template_strut:
                # 计算所需要获取的分组数，这边不需要去管引用数据集分组规则
                extra_datas_config = template_strut.extra_datas
                # 数据集规则
                datas_rule = extra_datas_config.quote_rule.datas_rule
                diff_group = len(struct_datas) or 1
                extra_data_group = diff_extra_datas(extra_datas_config, diff_group)
                if datas_rule in ("random", "sequence"):
                    if isinstance(extra_data_group, list) and extra_data_group:
                        extra_data_group = extra_data_group[0]
                    else:
                        extra_data_group = []

                extra_data_group_len = len(extra_data_group)

            if index == 0:
                for t, strut_data in enumerate(struct_datas):
                    # 如果只有一层映射
                    if len(sorted_main_strut_data) == 1:
                        if template_strut:
                            extra_datas = None
                            # 计算索引，使用取模来处理不够的情况
                            if extra_data_group:
                                extra_index = t % extra_data_group_len
                                extra_datas = extra_data_group[extra_index]
                            template_mock_data(
                                template_strut,
                                association_strut,
                                strut_data,
                                cal_rule_func,
                                None,
                                None,
                                association_data_list,
                                progress_bar,
                                extra_datas,
                                field_reflect,
                            )
                        else:
                            progress_bar.total += 1
                            progress_bar.update(1)

            else:
                # 后续其他结构的映射，则在索引0基础上进行结构间的映射
                cur_data_len = len(main_mock_dict[struct_name])  # 或者 n = 100
                reflect_data_len = len(struct_datas)

                # 计算每部分的基本值和余数
                base_count = cur_data_len // reflect_data_len  # 每组的基本数量
                remainder = cur_data_len % reflect_data_len  # 余数

                # 初始化拆分后的结果列表
                split_lists = []
                start_index = 0

                # 将第一层获取到的所有数据 按照当前映射主表数据进行拆分
                # 第一层数据 >= 映射主表的数据
                for i in range(reflect_data_len):
                    # 计算当前组的结束索引
                    end_index = start_index + base_count + (1 if i < remainder else 0)
                    split_lists.append(
                        main_mock_dict[struct_name][start_index:end_index]
                    )
                    start_index = end_index

                for i in range(len(struct_datas)):
                    # 应用的映射结构
                    reflect_data = struct_datas[i]
                    # 关联上层的数据
                    apply_data = split_lists[i]

                    for data in apply_data:
                        # association_mapping_data(field_reflect, data, reflect_data)
                        # 如果是最后的结构 进行模板映射
                        if index == (len(sorted_main_strut_data) - 1):
                            if template_strut:
                                extra_datas = None
                                # 计算索引，使用取模来处理不够的情况
                                if extra_data_group:
                                    extra_index = t % extra_data_group_len
                                    extra_datas = extra_data_group[extra_index]

                                template_mock_data(
                                    template_strut,
                                    data,
                                    reflect_data,
                                    cal_rule_func,
                                    None,
                                    None,
                                    association_data_list,
                                    progress_bar,
                                    extra_datas,
                                    field_reflect,
                                )
                            else:
                                progress_bar.total += 1
                                progress_bar.update(1)

        if association_name in main_mock_dict:
            main_mock_dict[association_name].extend(association_data_list)
        else:
            main_mock_dict[association_name] = copy.deepcopy(association_data_list)

        # mock_data_list = [
        #     convert_structure(instance) for instance in association_data_list
        # ]

        mock_list.append((file_name, association_name, association_data_list, args))

    progress_bar.close()
    # 归并mock_list 中元组的 0 和 1下标的值进行
    # 创建一个字典来归并元组
    merged_dict = {}

    for file_name, association_name, mock_data, args in mock_list:
        # 使用 (file_name, association_name) 作为字典的键
        key = (file_name, association_name)

        # 如果键不存在，则初始化一个列表
        if key not in merged_dict:
            merged_dict[key] = []

        # 将 mock_data 添加到相应的列表中
        merged_dict[key].extend(mock_data)

    merged_list = [(key[0], key[1], merged_dict[key], args) for key in merged_dict]

    return merged_list


__all__ = ["mock_data"]
